package hn.sigit.logic.viewer;

import hn.sigit.dao.hnd.cadastre.HND_LayerDAO;
import hn.sigit.dao.hnd.cadastre.HND_SpatialZoneDAO;
import hn.sigit.logic.general.GeneralHelper;
import hn.sigit.logic.general.ResourceBundleHelper;
import hn.sigit.logic.general.impl.GeneralHelperImpl;
import hn.sigit.model.commons.IParcel;
import hn.sigit.model.commons.IProperty;
import hn.sigit.model.commons.ISpatialZone;
import hn.sigit.model.hnd.cadastre.HND_Layer;
import hn.sigit.model.hnd.cadastre.HND_SpatialZone;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.model.SelectItem;

import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Polygon;

@Name("interactiveViewerHelper")
@Scope(value=ScopeType.CONVERSATION)
@AutoCreate
public class InteractiveViewerHelper implements Serializable {
	private static final long serialVersionUID = -5485155887832623658L;
	private static final String DEFAULT_LAYER = "sigit:hnd_parcel_polygon";
	
	
	private HND_SpatialZone selectedZone;
	private HND_Layer selectedLayer;
	private IProperty selectedProperty;
	private ISpatialZone zoomedInZone;
	
	private Double envelopeLeft = 0.0;
	private Double envelopeBottom = 0.0;
	private Double envelopeRight = 0.0;
	private Double envelopeTop = 0.0;

	private InteractiveViewerSearchHelper searchHelper;
	private InteractiveViewerRRRHelper rrrHelper;
	private InteractiveViewerLayerHelper layerHelper;
	private ResourceBundleHelper resBundle;
	
	private String highlightedSpatialUnitIds;
	
	private List<HND_SpatialZone> highlightedSpatialZoneList;
	private List<HND_Layer> layerList;
	private List<SelectItem> layerItems;
	
	
	private Boolean showSearchSpatialZoneToolbox = true;
	private Boolean showRightsToolbox = true;
	private Boolean showRestrictionsToolbox = true;
	private Boolean showResponsibilitiesToolbox = true;
	private Boolean showDataToolbox = true;
	private Boolean showSpatialAnalysisToolbox = true;
	private Boolean showSaveModificationButtons = false;
	private Boolean showHelpToolbox = true;
	private Boolean showTitle = true;
	private Boolean drawParcelLayerOnly = false;
	
	
	private HND_LayerConverter layerConverter;

	
	@In(create=true)
	private GeneralHelper generalHelper;
	
	@In(create=true)
	private MapHelper mapHelper;
	
	

	public InteractiveViewerHelper() {
		this.selectedLayer = findLayerByFullQualifiedName(DEFAULT_LAYER);

		this.mapHelper = (MapHelper) Component.getInstance("mapHelper", true);
		this.mapHelper.setSelectedLayerFQName(this.selectedLayer.getFullQualifiedName());
	}
	
	public ResourceBundleHelper getResBundle() {
		if (resBundle == null) {
			resBundle = getGeneralHelper().getResBundle();
		}
		return resBundle;
	}

	private GeneralHelper getGeneralHelper() {
		if (generalHelper == null) {
			this.generalHelper = (GeneralHelper) Component.getInstance("generalHelper", true);
		}
		return generalHelper;
	}
	
	public InteractiveViewerSearchHelper getSearchHelper() {
		if (searchHelper == null) {
			searchHelper = new InteractiveViewerSearchHelper(this);
		}
		return searchHelper;
	}

	public InteractiveViewerRRRHelper getRrrHelper() {
		if (rrrHelper == null) {
			rrrHelper = new InteractiveViewerRRRHelper(this);
		}
		return rrrHelper;
	}
	
	public InteractiveViewerLayerHelper getLayerHelper() {
		if (layerHelper == null) {
			layerHelper = new InteractiveViewerLayerHelper(this);
		}
		return layerHelper;
	}
	
	public String getMapOptions() {
		return mapHelper.mapOptions(drawParcelLayerOnly);
	}

	public HND_SpatialZone getSelectedZone() {
		return selectedZone;
	}
	public void setSelectedZone(HND_SpatialZone selectedZone) {
		if (this.selectedZone != selectedZone) {
			this.selectedZone = selectedZone;

			//mark the RRR fields to be updated/refreshed
			if (rrrHelper != null) {
				rrrHelper.setParcelRightsList(null);
				rrrHelper.setRrrSet(null);
				rrrHelper.setProperty(null);
			}
		}
	}

	public IProperty getSelectedProperty() {
		if (selectedProperty == null) {
			if (getSelectedZone() != null)
				selectedProperty = getSelectedZone().getProperty();
		}
		return selectedProperty;
	}
	public void setSelectedProperty(IProperty selectedProperty) {
		this.selectedProperty = selectedProperty;
	}

	public ISpatialZone getZoomedInZone() {
		return zoomedInZone;
	}
	public void setZoomedInZone(ISpatialZone zoomedInZone) {
		if (this.zoomedInZone == zoomedInZone) return;
		
		this.zoomedInZone = zoomedInZone;
		Polygon p = (Polygon) zoomedInZone.getShape();
		if (p != null) {
			Polygon pEnvelope = (Polygon) p.getEnvelope();
			Coordinate[] coords = pEnvelope.getCoordinates();
			
			envelopeLeft = envelopeBottom = envelopeRight = envelopeTop = null;
			if (coords.length > 1) {
				Double minx = Double.MAX_VALUE;
				Double miny = Double.MAX_VALUE;
				Double maxx = Double.MIN_VALUE;
				Double maxy = Double.MIN_VALUE;
				for (Coordinate c : coords) {
					if (c.x < minx) minx = c.x;
					if (c.x > maxx) maxx = c.x;
					if (c.y < miny) miny = c.y;
					if (c.y > maxy) maxy = c.y;
				}
				envelopeLeft = minx;
				envelopeBottom = miny;
				envelopeRight = maxx;
				envelopeTop = maxy;
			}
		}
	}
	
	public IParcel getSelectedParcel() {
		if (selectedZone != null && selectedZone instanceof IParcel)
			return (IParcel) selectedZone;
		return null;
	}

	public Double getEnvelopeLeft() {
		return envelopeLeft;
	}
	public Double getEnvelopeBottom() {
		return envelopeBottom;
	}
	public Double getEnvelopeRight() {
		return envelopeRight;
	}
	public Double getEnvelopeTop() {
		return envelopeTop;
	}


	public String getSelectedZoneText() {
		return generalHelper.getZoneUsefulName(getSelectedZone());
	}
	
		
	public String getCurrentLandUseName() {
		if (getSelectedZone() == null
				|| getSelectedZone().getCurrentLandUse() == null)
			return "";
		
		return getSelectedZone().getCurrentLandUse().getFullName();
	}
	public void setCurrentLandUseName(String landUseName) {
	}
	
	public String getProposedLandUseName() {
		if (getSelectedZone() == null
				|| getSelectedZone().getCurrentLandUse() == null)
			return "";
		return getSelectedZone().getProposedLandUse().getFullName();
	}
	public void setProposedLandUseName(String landUseName) {
	}

	public String getHighlightedSpatialUnitIds() {
		return highlightedSpatialUnitIds;
	}
	public void setHighlightedSpatialUnitIds(String highlightedSpatialUnitIds) {
		this.highlightedSpatialUnitIds = highlightedSpatialUnitIds;
		highlightedSpatialZoneList = null;
	}
	
	public List<HND_SpatialZone> getHighlightedSpatialZoneList() {
		HND_SpatialZone spatialZone;
		if (highlightedSpatialZoneList == null) {
			highlightedSpatialZoneList = new ArrayList<HND_SpatialZone>();
			if (highlightedSpatialUnitIds != null) {
				String[] suIds = highlightedSpatialUnitIds.split(",");
				for (String str : suIds) {
					if (!str.trim().equals("")) {
						spatialZone = HND_SpatialZoneDAO.loadSpatialZoneById(Long.parseLong(str));
						if (spatialZone != null)
							highlightedSpatialZoneList.add(spatialZone);
					}
				}
			}
		}
		return highlightedSpatialZoneList;
	}
	

	public List<HND_Layer> getLayerList() {
		if (layerList == null) {
			layerList = HND_LayerDAO.loadLayers(true);
		}
		return layerList;
	}
	
	public List<SelectItem> getLayerItems() {
		if (layerItems == null) {
			layerItems = new ArrayList<SelectItem>();
			for (HND_Layer layer : getLayerList())
				if (!drawParcelLayerOnly || layer.isParcelLayer())
					layerItems.add(new SelectItem(layer, layer.getName()));
		}
		return layerItems;
	}
	
	public HND_Layer getSelectedLayer() {
		return selectedLayer;
	}
	public void setSelectedLayer(HND_Layer selectedLayer) {
		this.selectedLayer = selectedLayer;
	}

	public Boolean getShowSearchSpatialZoneToolbox() {
		return showSearchSpatialZoneToolbox;
	}
	public void setShowSearchSpatialZoneToolbox(Boolean showSearchSpatialZoneToolbox) {
		if (showSearchSpatialZoneToolbox == null) return;
		this.showSearchSpatialZoneToolbox = showSearchSpatialZoneToolbox;
	}

	public Boolean getShowRightsToolbox() {
		return showRightsToolbox;
	}
	public void setShowRightsToolbox(Boolean showRightsToolbox) {
		if (showRightsToolbox == null) return;
		this.showRightsToolbox = showRightsToolbox;
	}

	public Boolean getShowRestrictionsToolbox() {
		return showRestrictionsToolbox;
	}
	public void setShowRestrictionsToolbox(Boolean showRestrictionsToolbox) {
		if (showRestrictionsToolbox == null) return;
		this.showRestrictionsToolbox = showRestrictionsToolbox;
	}

	public Boolean getShowResponsibilitiesToolbox() {
		return showResponsibilitiesToolbox;
	}
	public void setShowResponsibilitiesToolbox(Boolean showResponsibilitiesToolbox) {
		if (showResponsibilitiesToolbox == null) return;
		this.showResponsibilitiesToolbox = showResponsibilitiesToolbox;
	}

	public Boolean getShowDataToolbox() {
		return showDataToolbox;
	}
	public void setShowDataToolbox(Boolean showDataToolbox) {
		if (showDataToolbox == null) return;
		this.showDataToolbox = showDataToolbox;
	}

	public Boolean getShowSpatialAnalysisToolbox() {
		return showSpatialAnalysisToolbox;
	}
	public void setShowSpatialAnalysisToolbox(Boolean showSpatialAnalysisToolbox) {
		if (showSpatialAnalysisToolbox == null) return;
		this.showSpatialAnalysisToolbox = showSpatialAnalysisToolbox;
	}

	public Boolean getShowSaveModificationButtons() {
		return showSaveModificationButtons;
	}
	public void setShowSaveModificationButtons(Boolean showSaveModificationButtons) {
		if (showSaveModificationButtons == null) return;
		this.showSaveModificationButtons = showSaveModificationButtons;
	}
	
	public Boolean getDrawParcelLayerOnly() {
		return drawParcelLayerOnly;
	}
	public void setDrawParcelLayerOnly(Boolean drawParcelLayerOnly) {
		if (drawParcelLayerOnly == null) return;
		this.drawParcelLayerOnly = drawParcelLayerOnly;
	}

	public Boolean getShowHelpToolbox() {
		return showHelpToolbox;
	}
	public void setShowHelpToolbox(Boolean showHelpToolbox) {
		if (showHelpToolbox == null) return;
		this.showHelpToolbox = showHelpToolbox;
	}

	public Boolean getShowTitle() {
		return showTitle;
	}
	public void setShowTitle(Boolean showTitle) {
		if (showTitle == null) return;
		this.showTitle = showTitle;
	}

	
	public String getZoneSelectionRerenderString() {
		StringBuffer bs = new StringBuffer();
		
		if (showRightsToolbox) bs.append("panelRights,");
		if (showRestrictionsToolbox) bs.append("panelRestrictions,");
		if (showResponsibilitiesToolbox) bs.append("panelResponsibilities,");
		if (showDataToolbox) bs.append("panelData,");
		if (showSpatialAnalysisToolbox) bs.append("panelSpatialAnalysis,grpOperand1,");
		
		bs.deleteCharAt(bs.length()-1);
		
		return bs.toString();
	}

	
	public GeneralHelper getGeneralHelperInstance() {
		if (generalHelper == null) {
			generalHelper = new GeneralHelperImpl();
		}
		return generalHelper;
	}
	
	
	private HND_Layer findLayerByFullQualifiedName(String fullQualifiedName) {
		for (HND_Layer layer : getLayerList())
			if (layer.getFullQualifiedName().equals(fullQualifiedName))
				return layer;
		return null;
	}
	
	public HND_LayerConverter getLayerConverter() {
		if (layerConverter == null) {
			layerConverter = new HND_LayerConverter();
		}
		return layerConverter;
	}
	
	public class HND_LayerConverter implements Converter {
		@Override
		public Object getAsObject(FacesContext context, UIComponent component, String value) {
			for (HND_Layer layer : getLayerList())
				if (layer.getIID() == Long.parseLong(value))
					return layer;
			return null;
		}

		@Override
		public String getAsString(FacesContext context, UIComponent component, Object value) {
			return String.valueOf(((HND_Layer) value).getIID());
		}
	}
}
